#[allow(non_snake_case)]
use std::fmt;
use num_traits::FromPrimitive;

pub const EI_NIDENT: usize = 16;
/// ELF magic number byte 1
pub const ELFMAG0: u8 = 0x7f;
/// ELF magic number byte 2
pub const ELFMAG1: u8 = 0x45;
/// ELF magic number byte 3
pub const ELFMAG2: u8 = 0x4c;
/// ELF magic number byte 4
pub const ELFMAG3: u8 = 0x46;
/// Location of ELF pub enum field in ELF file header ident array
pub const EI_CLASS: usize = 4;
/// Location of data format field in ELF file header ident array
pub const EI_DATA: usize = 5;
/// Location of ELF version field in ELF file header ident array
pub const EI_VERSION: usize = 6;
/// Location of OS ABI field in ELF file header ident array
pub const EI_OSABI: usize = 7;
/// Location of ABI version field in ELF file header ident array
pub const EI_ABIVERSION: usize = 8;

pub const ELF_MAGIC :u32 = 0x464c457f;

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum ElfClass {
    ElfNone = 0x00,
    Elf32   = 0x01,
    Elf64   = 0x02,
}

impl From<u8> for ElfClass {
    fn from(elf_class: u8) -> Self {
        FromPrimitive::from_u8(elf_class)
            .expect(format!("Failed to convert u8 to elf class: {}", elf_class).as_str())
    }
}

impl fmt::Display for ElfClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            ElfClass::ElfNone => "Invalid",
            ElfClass::Elf32 => "32-bit",
            ElfClass::Elf64 => "64-bit"
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum ElfEndian {
    ElfDataNone = 0x00,
    ElfLittle   = 0x01,
    ElfBig      = 0x02,
}

impl From<u8> for ElfEndian {
    fn from(elf_endian: u8) -> Self {
        FromPrimitive::from_u8(elf_endian)
            .expect(format!("Failed to convert u8 to elf endian: {}", elf_endian).as_str())
    }
}

impl fmt::Display for ElfEndian {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            ElfEndian::ElfDataNone => "Invalid",
            ElfEndian::ElfLittle => "little endian",
            ElfEndian::ElfBig => "big endian"
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum OsAbi {
    None        = 0x00,
    HP_UX       = 0x01,
    NetBsd      = 0x02,
    Linux       = 0x03,
    GnuHurd     = 0x04,
    Solaris     = 0x06,
    Aix         = 0x07,
    Irix        = 0x08,
    FreeBsd     = 0x09,
    Tru64       = 0x0A,
    NovellModesto = 0x0B,
    OpenBsd     = 0x0C,
    OpenVms     = 0x0D,
    NonStopKernel   = 0x0E,
    Aros        = 0x0F,
    Fenix       = 0x10,
    Cloud       = 0x11,
    OpenVOS     = 0x12
}

impl From<u8> for OsAbi {
    fn from(os_abi: u8) -> Self {
        FromPrimitive::from_u8(os_abi)
            .expect(format!("Failed to convert u8 to os abi: {}", os_abi).as_str())
    }
}


impl fmt::Display for OsAbi {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            OsAbi::None             => "None",
            OsAbi::HP_UX            => "HP_UX",
            OsAbi::NetBsd           => "NetBsd",
            OsAbi::Linux            => "Linux",
            OsAbi::GnuHurd          => "GnuHurd",
            OsAbi::Solaris          => "Solaris",
            OsAbi::Aix              => "Aix",
            OsAbi::Irix             => "Irix",
            OsAbi::FreeBsd          => "FreeBsd",
            OsAbi::Tru64            => "Tru64",
            OsAbi::NovellModesto    => "NovellModesto",
            OsAbi::OpenBsd          => "OpenBsd",
            OsAbi::OpenVms          => "OpenVms",
            OsAbi::NonStopKernel    => "NonStopKernel",
            OsAbi::Aros             => "Aros",
            OsAbi::Fenix            => "Fenix",
            OsAbi::Cloud            => "Cloud",
            OsAbi::OpenVOS          => "OpenVOS",
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum ElfType {
    ET_NONE     = 0x0000,
    ET_REL      = 0x0001,
    ET_EXEC     = 0x0002,
    ET_DYN      = 0x0003,
    ET_CORE     = 0x0004,
    ET_LOOS     = 0xFE00,
    ET_HIOS     = 0xFEFF,
    ET_LOPROC   = 0xFF00,
    ET_HIPROC   = 0xFFFF,
}

impl From<u16> for ElfType {
    fn from(elf_type: u16) -> Self {
        FromPrimitive::from_u16(elf_type)
            .expect(format!("Failed to convert u16 to elf type: {}", elf_type).as_str())
    }
}

impl fmt::Display for ElfType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            ElfType::ET_NONE   => "ET_NONE",
            ElfType::ET_REL    => "ET_REL",
            ElfType::ET_EXEC   => "ET_EXEC",
            ElfType::ET_DYN    => "ET_DYN",
            ElfType::ET_CORE   => "ET_CORE",
            ElfType::ET_LOOS   => "ET_LOOS",
            ElfType::ET_HIOS   => "ET_HIOS",
            ElfType::ET_LOPROC => "ET_LOPROC",
            ElfType::ET_HIPROC => "ET_HIPROC",
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum ElfVersion {
    EV_NONE     = 0x00,
    EV_CURRENT  = 0x01,
}

impl From<u8> for ElfVersion {
    fn from(version: u8) -> Self {
        FromPrimitive::from_u8(version)
            .expect(format!("Failed to convert u8 to elf version: {}", version).as_str())
    }
}

impl fmt::Display for ElfVersion {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            ElfVersion::EV_NONE => "None",
            ElfVersion::EV_CURRENT => "Version 1.0"
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum SegmentType {
    PT_NULL         = 0x00000000,
    PT_LOAD         = 0x00000001,
    PT_DYNAMIC      = 0x00000002,
    PT_INTERP       = 0x00000003,
    PT_NOTE         = 0x00000004,
    PT_SHLIB        = 0x00000005,
    PT_PHDR         = 0x00000006,
    PT_TLS          = 0x00000007,
    PT_NUM          = 0x00000008,
    PT_LOOS         = 0x60000000,
    PT_GNU_EH_FRAME = 0x6474E550,
    PT_GNU_STACK    = 0x6474E551,
    PT_GNU_RELRO    = 0x6474E552,
    PT_SUNWBSS      = 0x6FFFFFFA,
    PT_SUNWSTACK    = 0x6FFFFFFB,
    PT_HIOS         = 0x6FFFFFFF,
    PT_ARCHEXT      = 0x70000000,
    PT_EXIDX        = 0x70000001,
    PT_HIPROC       = 0x7FFFFFFF,
}

impl From<u32> for SegmentType {
    fn from(seg_type: u32) -> Self {
        FromPrimitive::from_u32(seg_type)
            .expect(format!("Failed to convert u32 to segment type: {}", seg_type).as_str())
    }
}

impl fmt::Display for SegmentType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            SegmentType::PT_NULL           => "PT_NULL",
            SegmentType::PT_LOAD           => "PT_LOAD",
            SegmentType::PT_DYNAMIC        => "PT_DYNAMIC",
            SegmentType::PT_INTERP         => "PT_INTERP",
            SegmentType::PT_NOTE           => "PT_NOTE",
            SegmentType::PT_SHLIB          => "PT_SHLIB",
            SegmentType::PT_PHDR           => "PT_PHDR",
            SegmentType::PT_TLS            => "PT_TLS",
            SegmentType::PT_NUM            => "PT_NUM",
            SegmentType::PT_LOOS           => "PT_LOOS",
            SegmentType::PT_GNU_EH_FRAME   => "PT_GNU_EH_FRAME",
            SegmentType::PT_GNU_STACK      => "PT_GNU_STACK",
            SegmentType::PT_GNU_RELRO      => "PT_GNU_RELRO",
            SegmentType::PT_SUNWBSS        => "PT_SUNWBSS",
            SegmentType::PT_SUNWSTACK      => "PT_SUNWSTACK",
            SegmentType::PT_HIOS           => "PT_HIOS",
            SegmentType::PT_ARCHEXT        => "PT_ARCHEXT",
            SegmentType::PT_EXIDX          => "PT_EXIDX",
            SegmentType::PT_HIPROC         => "PT_HIPROC"
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum SegmentFlag {
    PF_X        = 0x00000001,
    PF_W        = 0x00000002,
    PF_R        = 0x00000004,
    PF_MASKPROC = 0xF0000000,
}

impl From<u32> for SegmentFlag {
    fn from(flag: u32) -> Self {
        FromPrimitive::from_u32(flag)
            .expect(format!("Failed to convert u32 to segment flag: {}", flag).as_str())
    }
}

impl fmt::Display for SegmentFlag {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            SegmentFlag::PF_X          => "PF_X",
            SegmentFlag::PF_W          => "PF_W",
            SegmentFlag::PF_R          => "PF_R",
            SegmentFlag::PF_MASKPROC   => "PF_MASKPROC",
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum DynamicTag {
    DT_NULL                 =         0,
    DT_NEEDED               =         1,
    DT_PLTRELSZ             =         2,
    DT_PLTGOT               =         3,
    DT_HASH                 =         4,
    DT_STRTAB               =         5,
    DT_SYMTAB               =         6,
    DT_RELA                 =         7,
    DT_RELASZ               =         8,
    DT_RELAENT              =         9,
    DT_STRSZ                =        10,
    DT_SYMENT               =        11,
    DT_INIT                 =        12,
    DT_FINI                 =        13,
    DT_SONAME               =        14,
    DT_RPATH                =        15,
    DT_SYMBOLIC             =        16,
    DT_REL                  =        17,
    DT_RELSZ                =        18,
    DT_RELENT               =        19,
    DT_PLTREL               =        20,
    DT_DEBUG                =        21,
    DT_TEXTREL              =        22,
    DT_JMPREL               =        23,
    DT_BIND_NOW             =        24,
    DT_INIT_ARRAY           =        25,
    DT_FINI_ARRAY           =        26,
    DT_INIT_ARRAYSZ         =        27,
    DT_FINI_ARRAYSZ         =        28,
    DT_RUNPATH              =        29,
    DT_FLAGS                =        30,
    DT_PREINIT_ARRAY        =        32,
    DT_PREINIT_ARRAYSZ      =        33,
    DT_LOOS                 =0x6000000d,
    DT_ANDROID_REL          =0x6000000f,
    DT_ANDROID_RELSZ        =0x60000010,
    DT_ANDROID_RELA         =0x60000011,
    DT_ANDROID_RELASZ       =0x60000012,
    DT_PACKERINFO_OFFSET    =0x6f000000,
    DT_RELR                 =0x6fffe000,
    DT_RELRSZ               =0x6fffe001,
    DT_RELRENT              =0x6fffe003,
    DT_RELRCOUNT            =0x6fffe005,
    DT_HIOS                 =0x6ffff000,
    DT_VALRNGLO             =0x6ffffd00,
    DT_VALRNGHI             =0x6ffffdff,
    DT_ADDRRNGLO            =0x6ffffe00,
    DT_GNU_HASH             =0x6ffffef5,
    DT_TLSDESC_PLT          =0x6ffffef6,
    DT_TLSDESC_GOT          =0x6ffffef7,
    DT_ADDRRNGHI            =0x6ffffeff,
    DT_VERSYM               =0x6ffffff0,
    DT_RELACOUNT            =0x6ffffff9,
    DT_RELCOUNT             =0x6ffffffa,
    DT_FLAGS_1              =0x6ffffffb,
    DT_VERDEF               =0x6ffffffc,
    DT_VERDEFNUM            =0x6ffffffd,
    DT_VERNEED              =0x6ffffffe,
    DT_VERNEEDNUM           =0x6fffffff,
    DT_OLD_HIOS             =0x70000000,
    DT_REGISTER             =0x70000001,
    DT_AUXILIARY            =0x7FFFFFFD,
    DT_USED                 =0x7FFFFFFE,
    DT_HIPROC               =0x7FFFFFFF,
}

impl From<i32> for DynamicTag {
    fn from(flag: i32) -> Self {
        FromPrimitive::from_i32(flag)
            .expect(format!("Failed to conver i32 to Dynamic flag: {}", flag).as_str())
    }
}

impl fmt::Display for DynamicTag {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            DynamicTag::DT_NULL => 				    "DT_NULL",
            DynamicTag::DT_NEEDED => 				"DT_NEEDED",
            DynamicTag::DT_PLTRELSZ => 				"DT_PLTRELSZ",
            DynamicTag::DT_PLTGOT => 				"DT_PLTGOT",
            DynamicTag::DT_HASH => 				    "DT_HASH",
            DynamicTag::DT_STRTAB => 				"DT_STRTAB",
            DynamicTag::DT_SYMTAB => 				"DT_SYMTAB",
            DynamicTag::DT_RELA => 				    "DT_RELA",
            DynamicTag::DT_RELASZ => 				"DT_RELASZ",
            DynamicTag::DT_RELAENT => 				"DT_RELAENT",
            DynamicTag::DT_STRSZ => 				"DT_STRSZ",
            DynamicTag::DT_SYMENT => 				"DT_SYMENT",
            DynamicTag::DT_INIT => 				    "DT_INIT",
            DynamicTag::DT_FINI => 				    "DT_FINI",
            DynamicTag::DT_SONAME => 				"DT_SONAME",
            DynamicTag::DT_RPATH => 				"DT_RPATH",
            DynamicTag::DT_SYMBOLIC => 				"DT_SYMBOLIC",
            DynamicTag::DT_REL => 				    "DT_REL",
            DynamicTag::DT_RELSZ => 				"DT_RELSZ",
            DynamicTag::DT_RELENT => 				"DT_RELENT",
            DynamicTag::DT_PLTREL => 				"DT_PLTREL",
            DynamicTag::DT_DEBUG => 				"DT_DEBUG",
            DynamicTag::DT_TEXTREL => 				"DT_TEXTREL",
            DynamicTag::DT_JMPREL => 				"DT_JMPREL",
            DynamicTag::DT_BIND_NOW => 				"DT_BIND_NOW",
            DynamicTag::DT_INIT_ARRAY => 			"DT_INIT_ARRAY",
            DynamicTag::DT_FINI_ARRAY => 			"DT_FINI_ARRAY",
            DynamicTag::DT_INIT_ARRAYSZ => 			"DT_INIT_ARRAYSZ",
            DynamicTag::DT_FINI_ARRAYSZ => 			"DT_FINI_ARRAYSZ",
            DynamicTag::DT_RUNPATH => 				"DT_RUNPATH",
            DynamicTag::DT_FLAGS => 				"DT_FLAGS",
            DynamicTag::DT_PREINIT_ARRAY => 	    "DT_PREINIT_ARRAY",
            DynamicTag::DT_PREINIT_ARRAYSZ => 		"DT_PREINIT_ARRAYSZ",
            DynamicTag::DT_LOOS => 				    "DT_LOOS",
            DynamicTag::DT_ANDROID_REL => 			"DT_ANDROID_REL",
            DynamicTag::DT_ANDROID_RELSZ => 		"DT_ANDROID_RELSZ",
            DynamicTag::DT_ANDROID_RELA => 			"DT_ANDROID_RELA",
            DynamicTag::DT_ANDROID_RELASZ => 		"DT_ANDROID_RELASZ",
            DynamicTag::DT_PACKERINFO_OFFSET => 	"DT_PACKERINFO_OFFSET",
            DynamicTag::DT_RELR => 				    "DT_RELR",
            DynamicTag::DT_RELRSZ => 				"DT_RELRSZ",
            DynamicTag::DT_RELRENT => 				"DT_RELRENT",
            DynamicTag::DT_RELRCOUNT => 			"DT_RELRCOUNT",
            DynamicTag::DT_HIOS => 				    "DT_HIOS",
            DynamicTag::DT_VALRNGLO => 				"DT_VALRNGLO",
            DynamicTag::DT_VALRNGHI => 				"DT_VALRNGHI",
            DynamicTag::DT_ADDRRNGLO => 			"DT_ADDRRNGLO",
            DynamicTag::DT_GNU_HASH => 				"DT_GNU_HASH",
            DynamicTag::DT_TLSDESC_PLT => 			"DT_TLSDESC_PLT",
            DynamicTag::DT_TLSDESC_GOT => 			"DT_TLSDESC_GOT",
            DynamicTag::DT_ADDRRNGHI => 			"DT_ADDRRNGHI",
            DynamicTag::DT_VERSYM => 				"DT_VERSYM",
            DynamicTag::DT_RELACOUNT => 			"DT_RELACOUNT",
            DynamicTag::DT_RELCOUNT => 				"DT_RELCOUNT",
            DynamicTag::DT_FLAGS_1 => 				"DT_FLAGS_1",
            DynamicTag::DT_VERDEF => 				"DT_VERDEF",
            DynamicTag::DT_VERDEFNUM => 			"DT_VERDEFNUM",
            DynamicTag::DT_VERNEED => 				"DT_VERNEED",
            DynamicTag::DT_VERNEEDNUM => 			"DT_VERNEEDNUM",
            DynamicTag::DT_OLD_HIOS => 				"DT_OLD_HIOS",
            DynamicTag::DT_REGISTER => 				"DT_REGISTER",
            DynamicTag::DT_AUXILIARY => 			"DT_AUXILIARY",
            DynamicTag::DT_USED => 				    "DT_USED",
            DynamicTag::DT_HIPROC => 				"DT_HIPROC",
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum SectionType {
    SHT_NULL = 0,
    SHT_PROGBITS = 1,
    SHT_SYMTAB = 2,
    SHT_STRTAB = 3,
    SHT_RELA = 4,
    SHT_HASH = 5,
    SHT_DYNAMIC = 6,
    SHT_NOTE = 7,
    SHT_NOBITS = 8,
    SHT_REL = 9,
    SHT_SHLIB = 10,
    SHT_DYNSYM = 11,
    SHT_INIT_ARRAY = 14,
    SHT_FINI_ARRAY = 15,
    SHT_PREINIT_ARRAY = 16,
    SHT_GROUP = 17,
    SHT_SYMTAB_SHNDX = 18,
    SHT_NUM = 19,
    SHT_LOOS = 0x60000000,
    SHT_ANDROID_REL = 0x60000001,
    SHT_ANDROID_RELA = 0x60000002,
    SHT_LLVM_ODRTAB = 0x6fff4c00,
    SHT_LLVM_LINKER_OPTIONS = 0x6fff4c01,
    SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c02,
    SHT_LLVM_ADDRSIG = 0x6fff4c03,
    SHT_LLVM_DEPENDENT_LIBRARIES = 0x6fff4c04,
    SHT_LLVM_SYMPART = 0x6fff4c05,
    SHT_LLVM_PART_EHDR = 0x6fff4c06,
    SHT_LLVM_PART_PHDR = 0x6fff4c07,
    SHT_ANDROID_RELR = 0x6fffff00,
    SHT_GNU_ATTRIBUTES = 0x6ffffff5,
    SHT_GNU_HASH = 0x6ffffff6,
    SHT_GNU_LIBLIST = 0x6ffffff7,
    SHT_CHECKSUM = 0x6ffffff8,
    SHT_SUNW_move = 0x6ffffffa,
    SHT_SUNW_COMDAT = 0x6ffffffb,
    SHT_SUNW_syminfo = 0x6ffffffc,
    SHT_GNU_verdef = 0x6ffffffd,
    SHT_GNU_verneed = 0x6ffffffe,
    SHT_GNU_versym = 0x6fffffff,
    SHT_LOPROC = 0x70000000,
    SHT_ARM_EXIDX = 0x70000001,
    SHT_ARM_PREEMPTMAP = 0x70000002,
    SHT_ARM_ATTRIBUTES = 0x70000003,
    SHT_ARM_DEBUGOVERLAY = 0x70000004,
    SHT_ARM_OVERLATSECTION = 0x70000005,
    SHT_HIPROC = 0x7fffffff,
    SHT_LOUSER = 0x80000000,
    SHT_HIUSER = 0x8fffffff,

}


impl From<u32> for SectionType {
    fn from(section_type: u32) -> Self {
        FromPrimitive::from_u32(section_type)
            .expect(format!("Failed to conver i32 to section type : {}", section_type).as_str())
    }
}

impl fmt::Display for SectionType{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            SectionType::SHT_NULL                        => "SHT_NULL",
            SectionType::SHT_PROGBITS                    => "SHT_PROGBITS",
            SectionType::SHT_SYMTAB                      => "SHT_SYMTAB",
            SectionType::SHT_STRTAB                      => "SHT_STRTAB",
            SectionType::SHT_RELA                        => "SHT_RELA",
            SectionType::SHT_HASH                        => "SHT_HASH",
            SectionType::SHT_DYNAMIC                     => "SHT_DYNAMIC",
            SectionType::SHT_NOTE                        => "SHT_NOTE",
            SectionType::SHT_NOBITS                      => "SHT_NOBITS",
            SectionType::SHT_REL                         => "SHT_REL",
            SectionType::SHT_SHLIB                       => "SHT_SHLIB",
            SectionType::SHT_DYNSYM                      => "SHT_DYNSYM",
            SectionType::SHT_INIT_ARRAY                  => "SHT_INIT_ARRAY",
            SectionType::SHT_FINI_ARRAY                  => "SHT_FINI_ARRAY",
            SectionType::SHT_PREINIT_ARRAY               => "SHT_PREINIT_ARRAY",
            SectionType::SHT_GROUP                       => "SHT_GROUP",
            SectionType::SHT_SYMTAB_SHNDX                => "SHT_SYMTAB_SHNDX",
            SectionType::SHT_NUM                         => "SHT_NUM",
            SectionType::SHT_LOOS                        => "SHT_LOOS",
            SectionType::SHT_ANDROID_REL                 => "SHT_ANDROID_REL",
            SectionType::SHT_ANDROID_RELA                => "SHT_ANDROID_RELA",
            SectionType::SHT_LLVM_ODRTAB                 => "SHT_LLVM_ODRTAB",
            SectionType::SHT_LLVM_LINKER_OPTIONS         => "SHT_LLVM_LINKER_OPTIONS",
            SectionType::SHT_LLVM_CALL_GRAPH_PROFILE     => "SHT_LLVM_CALL_GRAPH_PROFILE",
            SectionType::SHT_LLVM_ADDRSIG                => "SHT_LLVM_ADDRSIG",
            SectionType::SHT_LLVM_DEPENDENT_LIBRARIES    => "SHT_LLVM_DEPENDENT_LIBRARIES",
            SectionType::SHT_LLVM_SYMPART                => "SHT_LLVM_SYMPART",
            SectionType::SHT_LLVM_PART_EHDR              => "SHT_LLVM_PART_EHDR",
            SectionType::SHT_LLVM_PART_PHDR              => "SHT_LLVM_PART_PHDR",
            SectionType::SHT_ANDROID_RELR                => "SHT_ANDROID_RELR",
            SectionType::SHT_GNU_ATTRIBUTES              => "SHT_GNU_ATTRIBUTES",
            SectionType::SHT_GNU_HASH                    => "SHT_GNU_HASH",
            SectionType::SHT_GNU_LIBLIST                 => "SHT_GNU_LIBLIST",
            SectionType::SHT_CHECKSUM                    => "SHT_CHECKSUM",
            SectionType::SHT_SUNW_move                   => "SHT_SUNW_move",
            SectionType::SHT_SUNW_COMDAT                 => "SHT_SUNW_COMDAT",
            SectionType::SHT_SUNW_syminfo                => "SHT_SUNW_syminfo",
            SectionType::SHT_GNU_verdef                  => "SHT_GNU_verdef",
            SectionType::SHT_GNU_verneed                 => "SHT_GNU_verneed",
            SectionType::SHT_GNU_versym                  => "SHT_GNU_versym",
            SectionType::SHT_LOPROC                      => "SHT_LOPROC",
            SectionType::SHT_ARM_EXIDX                   => "SHT_ARM_EXIDX",
            SectionType::SHT_ARM_PREEMPTMAP              => "SHT_ARM_PREEMPTMAP",
            SectionType::SHT_ARM_ATTRIBUTES              => "SHT_ARM_ATTRIBUTES",
            SectionType::SHT_ARM_DEBUGOVERLAY            => "SHT_ARM_DEBUGOVERLAY",
            SectionType::SHT_ARM_OVERLATSECTION          => "SHT_ARM_OVERLATSECTION",
            SectionType::SHT_HIPROC                      => "SHT_HIPROC",
            SectionType::SHT_LOUSER                      => "SHT_LOUSER",
            SectionType::SHT_HIUSER                      => "SHT_HIUSER",
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum SectionFlag {
    SHF_WRITE               = 0x01,
    SHF_ALLOC               = 0x02,
    SHF_EXECINSTR           = 0x04,
    SHF_MERGE               = 0x10,
    SHF_STRINGS             = 0x20,
    SHF_INFO_LINK           = 0x40,
    SHF_LINK_ORDER          = 0x80,
    SHF_OS_NONCONFORMING    = 0x100,
    SHF_GROUP               = 0x200,
    SHF_TLS                 = 0x400,
    SHF_COMPRESSED          = 0x800,
    SHF_RELA_LIVEPATCH      = 0x0010000,
    SHF_RO_AFTER_INIT       = 0x0020000,
    SHF_MASKOS              = 0x0FF0000,
    SHF_MASKPROC            = 0xF0000000,
}

impl From<u32> for SectionFlag {
    fn from(section_flag: u32) -> Self {
        FromPrimitive::from_u32(section_flag)
            .expect(format!("Failed to conver i32 to section flag : {}", section_flag).as_str())
    }
}

impl fmt::Display for SectionFlag{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            SectionFlag::SHF_WRITE => {"SHF_WRITE"},
            SectionFlag::SHF_ALLOC => {"SHF_ALLOC"},
            SectionFlag::SHF_EXECINSTR => {"SHF_EXECINSTR"},
            SectionFlag::SHF_RELA_LIVEPATCH => {"SHF_RELA_LIVEPATCH"},
            SectionFlag::SHF_RO_AFTER_INIT => {"SHF_RO_AFTER_INIT"},
            SectionFlag::SHF_MASKPROC => {"SHF_MASKPROC"},
            SectionFlag::SHF_MERGE => {"SHF_MERGE"},
            SectionFlag::SHF_STRINGS => {"SHF_STRINGS"},
            SectionFlag::SHF_INFO_LINK => {"SHF_INFO_LINK"},
            SectionFlag::SHF_LINK_ORDER => {"SHF_LINK_ORDER"},
            SectionFlag::SHF_OS_NONCONFORMING => {"SHF_OS_NONCONFORMING"},
            SectionFlag::SHF_GROUP => {"SHF_GROUP"},
            SectionFlag::SHF_TLS => {"SHF_TLS"},
            SectionFlag::SHF_COMPRESSED => {"SHF_COMPRESSED"},
            SectionFlag::SHF_MASKOS => {"SHF_MASKOS"},
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum SectionSpecialIndex {
    SHN_UNDEF       = 0,
    SHN_LORESERVE   = 0xFF00,
    SHN_HIPROC      = 0xFF1F,
    SHN_LOOS        = 0xFF20,
    SHN_HIOS        = 0xFF3F,
    SHN_ABS         = 0xFFF1,
    SHN_COMMON      = 0xFFF2,
    SHN_XINDEX      = 0xFFFF,
}

impl From<u16> for SectionSpecialIndex {
    fn from(idx: u16) -> Self {
        FromPrimitive::from_u16(idx)
            .expect(format!("Failed to conver i32 to section index : {}", idx).as_str())
    }
}


impl fmt::Display for SectionSpecialIndex{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            SectionSpecialIndex::SHN_UNDEF => {"SHN_UNDEF"},
            SectionSpecialIndex::SHN_LORESERVE => {"SHN_LORESERVE"},
            SectionSpecialIndex::SHN_HIPROC => {"SHN_HIPROC"},
            SectionSpecialIndex::SHN_LOOS => {"SHN_LOOS"},
            SectionSpecialIndex::SHN_HIOS => {"SHN_HIOS"},
            SectionSpecialIndex::SHN_ABS => {"SHN_ABS"},
            SectionSpecialIndex::SHN_COMMON => {"SHN_COMMON"},
            SectionSpecialIndex::SHN_XINDEX => {"SHN_XINDEX"},
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum ElfSymbolBind {
    STB_LOCAL   = 0,
    STB_GLOBAL  = 1,
    STB_WEAK    = 2,
    STB_LOOS    = 10,
    STB_HIOS    = 12,
    STB_LOPROC  = 13,
    STB_HIPROC  = 15,
}

impl From<u32> for ElfSymbolBind {
    fn from(bind: u32) -> Self {
        FromPrimitive::from_u32(bind)
            .expect(format!("Failed to conver i32 to symbol bind : {}", bind).as_str())
    }
}


impl fmt::Display for ElfSymbolBind{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            ElfSymbolBind::STB_LOCAL => {"STB_LOCAL"},
            ElfSymbolBind::STB_GLOBAL => {"STB_GLOBAL"},
            ElfSymbolBind::STB_WEAK => {"STB_WEAK"},
            ElfSymbolBind::STB_LOOS => {"STB_LOOS"},
            ElfSymbolBind::STB_HIOS => {"STB_HIOS"},
            ElfSymbolBind::STB_LOPROC => {"STB_LOPROC"},
            ElfSymbolBind::STB_HIPROC => {"STB_HIPROC"},
        };
        write!(f, "{}", str)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum ElfSymbolType {
    STT_NOTYPE      = 0,
    STT_OBJECT      = 1,
    STT_FUNC        = 2,
    STT_SECTION     = 3,
    STT_FILE        = 4,
    STT_COMMON      = 5,
    STT_TLS         = 6,
    STT_GNU_IFUNC   = 10,
    STT_HIOS        = 12,
    STT_LOPROC      = 13,
    STT_HIPROC      = 15,
}

impl fmt::Display for ElfSymbolType{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            ElfSymbolType::STT_NOTYPE => {"STT_NOTYPE"},
            ElfSymbolType::STT_OBJECT => {"STT_OBJECT"},
            ElfSymbolType::STT_FUNC => {"STT_FUNC"},
            ElfSymbolType::STT_SECTION => {"STT_SECTION"},
            ElfSymbolType::STT_FILE => {"STT_FILE"},
            ElfSymbolType::STT_COMMON => {"STT_COMMON"},
            ElfSymbolType::STT_TLS => {"STT_TLS"},
            ElfSymbolType::STT_GNU_IFUNC => {"STT_GNU_IFUNC"},
            ElfSymbolType::STT_HIOS => {"STT_HIOS"},
            ElfSymbolType::STT_LOPROC => {"STT_LOPROC"},
            ElfSymbolType::STT_HIPROC => {"STT_HIPROC"},
        };
        write!(f, "{}", str)
    }
}

#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum ElfSymbolVisibility {
    STV_DEFAULT     = 0,
    STV_INTERNAL    = 1,
    STV_HIDDEN      = 2,
    STV_PROTECTED   = 3,
}

impl fmt::Display for ElfSymbolVisibility{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            ElfSymbolVisibility::STV_DEFAULT => {"STV_DEFAULT"},
            ElfSymbolVisibility::STV_INTERNAL => {"STV_INTERNAL"},
            ElfSymbolVisibility::STV_HIDDEN => {"STV_HIDDEN"},
            ElfSymbolVisibility::STV_PROTECTED => {"STV_PROTECTED"},
        };
        write!(f, "{}", str)
    }
}


#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, ToPrimitive)]
pub enum RelocationType {
    R_ARM_NONE = 0,
    R_ARM_PC24 = 1,
    R_ARM_ABS32 = 2,
    R_ARM_REL32 = 3,
    R_ARM_PC13 = 4,
    R_ARM_ABS16 = 5,
    R_ARM_ABS12 = 6,
    R_ARM_THM_ABS5 = 7,
    R_ARM_ABS8 = 8,
    R_ARM_SBREL32 = 9,
    R_ARM_THM_PC22 = 10,
    R_ARM_THM_PC8 = 11,
    R_ARM_AMP_VCALL9 = 12,
    R_ARM_TLS_DESC = 13,
    R_ARM_THM_SWI8 = 14,
    R_ARM_XPC25 = 15,
    R_ARM_THM_XPC22 = 16,
    R_ARM_TLS_DTPMOD32 = 17,
    R_ARM_TLS_DTPOFF32 = 18,
    R_ARM_TLS_TPOFF32 = 19,
    R_ARM_COPY = 20,
    R_ARM_GLOB_DAT = 21,
    R_ARM_JUMP_SLOT = 22,
    R_ARM_RELATIVE = 23,
    R_ARM_GOTOFF = 24,
    R_ARM_GOTPC = 25,
    R_ARM_GOT32 = 26,
    R_ARM_PLT32 = 27,
    R_ARM_CALL = 28,
    R_ARM_JUMP24 = 29,
    R_ARM_THM_JUMP24 = 30,
    R_ARM_BASE_ABS = 31,
    R_ARM_ALU_PCREL_7_0 = 32,
    R_ARM_ALU_PCREL_15_8 = 33,
    R_ARM_ALU_PCREL_23_15 = 34,
    R_ARM_ALU_SBREL_11_0 = 35,
    R_ARM_ALU_SBREL_19_12 = 36,
    R_ARM_ALU_SBREL_27_20 = 37,
    R_ARM_TARGET1 = 38,
    R_ARM_SBREL31 = 39,
    R_ARM_V4BX = 40,
    R_ARM_TARGET2 = 41,
    R_ARM_PREL31 = 42,
    R_ARM_MOVW_ABS_NC = 43,
    R_ARM_MOVT_ABS = 44,
    R_ARM_MOVW_PREL_NC = 45,
    R_ARM_MOVT_PREL = 46,
    R_ARM_THM_MOVW_ABS_NC = 47,
    R_ARM_THM_MOVT_ABS = 48,
    R_ARM_THM_MOVW_PREL_NC = 49,
    R_ARM_THM_MOVT_PREL = 50,
    R_ARM_GNU_VTENTRY = 100,
    R_ARM_GNU_VTINHERIT = 101,
    R_ARM_THM_PC11 = 102,
    R_ARM_THM_PC9 = 103,
    R_ARM_TLS_GD32 = 104,
    R_ARM_TLS_LDM32 = 105,
    R_ARM_TLS_LDO32 = 106,
    R_ARM_TLS_IE32 = 107,
    R_ARM_TLS_LE32 = 108,
    R_ARM_TLS_LDO12 = 109,
    R_ARM_TLS_LE12 = 110,
    R_ARM_TLS_IE12GP = 111,
    R_ARM_IRELATIVE = 160,
    R_ARM_RXPC25 = 249,
    R_ARM_RSBREL32 = 250,
    R_ARM_THM_RPC22 = 251,
    R_ARM_RREL32 = 252,
    R_ARM_RABS32 = 253,
    R_ARM_RPC24 = 254,
    R_ARM_RBASE = 255,
    R_AARCH64_NONE = 256,
    R_AARCH64_ABS64 = 257,
    R_AARCH64_ABS32 = 258,
    R_AARCH64_ABS16 = 259,
    R_AARCH64_PREL64 = 260,
    R_AARCH64_PREL32 = 261,
    R_AARCH64_PREL16 = 262,
    R_AARCH64_MOVW_UABS_G0 = 263,
    R_AARCH64_MOVW_UABS_G0_NC = 264,
    R_AARCH64_MOVW_UABS_G1 = 265,
    R_AARCH64_MOVW_UABS_G1_NC = 266,
    R_AARCH64_MOVW_UABS_G2 = 267,
    R_AARCH64_MOVW_UABS_G2_NC = 268,
    R_AARCH64_MOVW_UABS_G3 = 269,
    R_AARCH64_MOVW_SABS_G0 = 270,
    R_AARCH64_MOVW_SABS_G1 = 271,
    R_AARCH64_MOVW_SABS_G2 = 272,
    R_AARCH64_LD_PREL_LO19 = 273,
    R_AARCH64_ADR_PREL_LO21 = 274,
    R_AARCH64_ADR_PREL_PG_HI21 = 275,
    R_AARCH64_ADR_PREL_PG_HI21_NC = 276,
    R_AARCH64_ADD_ABS_LO12_NC = 277,
    R_AARCH64_LDST8_ABS_LO12_NC = 278,
    R_AARCH64_TSTBR14 = 279,
    R_AARCH64_CONDBR19 = 280,
    R_AARCH64_JUMP26 = 282,
    R_AARCH64_CALL26 = 283,
    R_AARCH64_LDST16_ABS_LO12_NC = 284,
    R_AARCH64_LDST32_ABS_LO12_NC = 285,
    R_AARCH64_LDST64_ABS_LO12_NC = 286,
    R_AARCH64_LDST128_ABS_LO12_NC = 299,
    R_AARCH64_MOVW_PREL_G0 = 287,
    R_AARCH64_MOVW_PREL_G0_NC = 288,
    R_AARCH64_MOVW_PREL_G1 = 289,
    R_AARCH64_MOVW_PREL_G1_NC = 290,
    R_AARCH64_MOVW_PREL_G2 = 291,
    R_AARCH64_MOVW_PREL_G2_NC = 292,
    R_AARCH64_MOVW_PREL_G3 = 293,
    R_AARCH64_COPY = 1024,
    R_AARCH64_GLOB_DAT = 1025,
    R_AARCH64_JUMP_SLOT = 1026,
    R_AARCH64_RELATIVE = 1027,
    R_AARCH64_TLS_DTPREL64 = 1028,
    R_AARCH64_TLS_DTPMOD64 = 1029,
    R_AARCH64_TLS_TPREL64 = 1030,
    R_AARCH64_TLSDESC = 1031,
    R_AARCH64_IRELATIVE = 1032,
}

impl fmt::Display for RelocationType{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            RelocationType::R_ARM_NONE                      =>"RelocationType::R_ARM_NONE",
            RelocationType::R_ARM_PC24                      =>"RelocationType::R_ARM_PC24",
            RelocationType::R_ARM_ABS32                     =>"RelocationType::R_ARM_ABS32",
            RelocationType::R_ARM_REL32                     =>"RelocationType::R_ARM_REL32",
            RelocationType::R_ARM_PC13                      =>"RelocationType::R_ARM_PC13",
            RelocationType::R_ARM_ABS16                     =>"RelocationType::R_ARM_ABS16",
            RelocationType::R_ARM_ABS12                     =>"RelocationType::R_ARM_ABS12",
            RelocationType::R_ARM_THM_ABS5                  =>"RelocationType::R_ARM_THM_ABS5",
            RelocationType::R_ARM_ABS8                      =>"RelocationType::R_ARM_ABS8",
            RelocationType::R_ARM_SBREL32                   =>"RelocationType::R_ARM_SBREL32",
            RelocationType::R_ARM_THM_PC22                  =>"RelocationType::R_ARM_THM_PC22",
            RelocationType::R_ARM_THM_PC8                   =>"RelocationType::R_ARM_THM_PC8",
            RelocationType::R_ARM_AMP_VCALL9                =>"RelocationType::R_ARM_AMP_VCALL9",
            RelocationType::R_ARM_TLS_DESC                  =>"RelocationType::R_ARM_TLS_DESC",
            RelocationType::R_ARM_THM_SWI8                  =>"RelocationType::R_ARM_THM_SWI8",
            RelocationType::R_ARM_XPC25                     =>"RelocationType::R_ARM_XPC25",
            RelocationType::R_ARM_THM_XPC22                 =>"RelocationType::R_ARM_THM_XPC22",
            RelocationType::R_ARM_TLS_DTPMOD32              =>"RelocationType::R_ARM_TLS_DTPMOD32",
            RelocationType::R_ARM_TLS_DTPOFF32              =>"RelocationType::R_ARM_TLS_DTPOFF32",
            RelocationType::R_ARM_TLS_TPOFF32               =>"RelocationType::R_ARM_TLS_TPOFF32",
            RelocationType::R_ARM_COPY                      =>"RelocationType::R_ARM_COPY",
            RelocationType::R_ARM_GLOB_DAT                  =>"RelocationType::R_ARM_GLOB_DAT",
            RelocationType::R_ARM_JUMP_SLOT                 =>"RelocationType::R_ARM_JUMP_SLOT",
            RelocationType::R_ARM_RELATIVE                  =>"RelocationType::R_ARM_RELATIVE",
            RelocationType::R_ARM_GOTOFF                    =>"RelocationType::R_ARM_GOTOFF",
            RelocationType::R_ARM_GOTPC                     =>"RelocationType::R_ARM_GOTPC",
            RelocationType::R_ARM_GOT32                     =>"RelocationType::R_ARM_GOT32",
            RelocationType::R_ARM_PLT32                     =>"RelocationType::R_ARM_PLT32",
            RelocationType::R_ARM_CALL                      =>"RelocationType::R_ARM_CALL",
            RelocationType::R_ARM_JUMP24                    =>"RelocationType::R_ARM_JUMP24",
            RelocationType::R_ARM_THM_JUMP24                =>"RelocationType::R_ARM_THM_JUMP24",
            RelocationType::R_ARM_BASE_ABS                  =>"RelocationType::R_ARM_BASE_ABS",
            RelocationType::R_ARM_ALU_PCREL_7_0             =>"RelocationType::R_ARM_ALU_PCREL_7_0",
            RelocationType::R_ARM_ALU_PCREL_15_8            =>"RelocationType::R_ARM_ALU_PCREL_15_8",
            RelocationType::R_ARM_ALU_PCREL_23_15           =>"RelocationType::R_ARM_ALU_PCREL_23_15",
            RelocationType::R_ARM_ALU_SBREL_11_0            =>"RelocationType::R_ARM_ALU_SBREL_11_0",
            RelocationType::R_ARM_ALU_SBREL_19_12           =>"RelocationType::R_ARM_ALU_SBREL_19_12",
            RelocationType::R_ARM_ALU_SBREL_27_20           =>"RelocationType::R_ARM_ALU_SBREL_27_20",
            RelocationType::R_ARM_TARGET1                   =>"RelocationType::R_ARM_TARGET1",
            RelocationType::R_ARM_SBREL31                   =>"RelocationType::R_ARM_SBREL31",
            RelocationType::R_ARM_V4BX                      =>"RelocationType::R_ARM_V4BX",
            RelocationType::R_ARM_TARGET2                   =>"RelocationType::R_ARM_TARGET2",
            RelocationType::R_ARM_PREL31                    =>"RelocationType::R_ARM_PREL31",
            RelocationType::R_ARM_MOVW_ABS_NC               =>"RelocationType::R_ARM_MOVW_ABS_NC",
            RelocationType::R_ARM_MOVT_ABS                  =>"RelocationType::R_ARM_MOVT_ABS",
            RelocationType::R_ARM_MOVW_PREL_NC              =>"RelocationType::R_ARM_MOVW_PREL_NC",
            RelocationType::R_ARM_MOVT_PREL                 =>"RelocationType::R_ARM_MOVT_PREL",
            RelocationType::R_ARM_THM_MOVW_ABS_NC           =>"RelocationType::R_ARM_THM_MOVW_ABS_NC",
            RelocationType::R_ARM_THM_MOVT_ABS              =>"RelocationType::R_ARM_THM_MOVT_ABS",
            RelocationType::R_ARM_THM_MOVW_PREL_NC          =>"RelocationType::R_ARM_THM_MOVW_PREL_NC",
            RelocationType::R_ARM_THM_MOVT_PREL             =>"RelocationType::R_ARM_THM_MOVT_PREL",
            RelocationType::R_ARM_GNU_VTENTRY               =>"RelocationType::R_ARM_GNU_VTENTRY",
            RelocationType::R_ARM_GNU_VTINHERIT             =>"RelocationType::R_ARM_GNU_VTINHERIT",
            RelocationType::R_ARM_THM_PC11                  =>"RelocationType::R_ARM_THM_PC11",
            RelocationType::R_ARM_THM_PC9                   =>"RelocationType::R_ARM_THM_PC9",
            RelocationType::R_ARM_TLS_GD32                  =>"RelocationType::R_ARM_TLS_GD32",
            RelocationType::R_ARM_TLS_LDM32                 =>"RelocationType::R_ARM_TLS_LDM32",
            RelocationType::R_ARM_TLS_LDO32                 =>"RelocationType::R_ARM_TLS_LDO32",
            RelocationType::R_ARM_TLS_IE32                  =>"RelocationType::R_ARM_TLS_IE32",
            RelocationType::R_ARM_TLS_LE32                  =>"RelocationType::R_ARM_TLS_LE32",
            RelocationType::R_ARM_TLS_LDO12                 =>"RelocationType::R_ARM_TLS_LDO12",
            RelocationType::R_ARM_TLS_LE12                  =>"RelocationType::R_ARM_TLS_LE12",
            RelocationType::R_ARM_TLS_IE12GP                =>"RelocationType::R_ARM_TLS_IE12GP",
            RelocationType::R_ARM_IRELATIVE                 =>"RelocationType::R_ARM_IRELATIVE",
            RelocationType::R_ARM_RXPC25                    =>"RelocationType::R_ARM_RXPC25",
            RelocationType::R_ARM_RSBREL32                  =>"RelocationType::R_ARM_RSBREL32",
            RelocationType::R_ARM_THM_RPC22                 =>"RelocationType::R_ARM_THM_RPC22",
            RelocationType::R_ARM_RREL32                    =>"RelocationType::R_ARM_RREL32",
            RelocationType::R_ARM_RABS32                    =>"RelocationType::R_ARM_RABS32",
            RelocationType::R_ARM_RPC24                     =>"RelocationType::R_ARM_RPC24",
            RelocationType::R_ARM_RBASE                     =>"RelocationType::R_ARM_RBASE",
            RelocationType::R_AARCH64_NONE                  =>"RelocationType::R_AARCH64_NONE",
            RelocationType::R_AARCH64_ABS64                 =>"RelocationType::R_AARCH64_ABS64",
            RelocationType::R_AARCH64_ABS32                 =>"RelocationType::R_AARCH64_ABS32",
            RelocationType::R_AARCH64_ABS16                 =>"RelocationType::R_AARCH64_ABS16",
            RelocationType::R_AARCH64_PREL64                =>"RelocationType::R_AARCH64_PREL64",
            RelocationType::R_AARCH64_PREL32                =>"RelocationType::R_AARCH64_PREL32",
            RelocationType::R_AARCH64_PREL16                =>"RelocationType::R_AARCH64_PREL16",
            RelocationType::R_AARCH64_MOVW_UABS_G0          =>"RelocationType::R_AARCH64_MOVW_UABS_G0",
            RelocationType::R_AARCH64_MOVW_UABS_G0_NC       =>"RelocationType::R_AARCH64_MOVW_UABS_G0_NC",
            RelocationType::R_AARCH64_MOVW_UABS_G1          =>"RelocationType::R_AARCH64_MOVW_UABS_G1",
            RelocationType::R_AARCH64_MOVW_UABS_G1_NC       =>"RelocationType::R_AARCH64_MOVW_UABS_G1_NC",
            RelocationType::R_AARCH64_MOVW_UABS_G2          =>"RelocationType::R_AARCH64_MOVW_UABS_G2",
            RelocationType::R_AARCH64_MOVW_UABS_G2_NC       =>"RelocationType::R_AARCH64_MOVW_UABS_G2_NC",
            RelocationType::R_AARCH64_MOVW_UABS_G3          =>"RelocationType::R_AARCH64_MOVW_UABS_G3",
            RelocationType::R_AARCH64_MOVW_SABS_G0          =>"RelocationType::R_AARCH64_MOVW_SABS_G0",
            RelocationType::R_AARCH64_MOVW_SABS_G1          =>"RelocationType::R_AARCH64_MOVW_SABS_G1",
            RelocationType::R_AARCH64_MOVW_SABS_G2          =>"RelocationType::R_AARCH64_MOVW_SABS_G2",
            RelocationType::R_AARCH64_LD_PREL_LO19          =>"RelocationType::R_AARCH64_LD_PREL_LO19",
            RelocationType::R_AARCH64_ADR_PREL_LO21         =>"RelocationType::R_AARCH64_ADR_PREL_LO21",
            RelocationType::R_AARCH64_ADR_PREL_PG_HI21      =>"RelocationType::R_AARCH64_ADR_PREL_PG_HI21",
            RelocationType::R_AARCH64_ADR_PREL_PG_HI21_NC   =>"RelocationType::R_AARCH64_ADR_PREL_PG_HI21_NC",
            RelocationType::R_AARCH64_ADD_ABS_LO12_NC       =>"RelocationType::R_AARCH64_ADD_ABS_LO12_NC",
            RelocationType::R_AARCH64_LDST8_ABS_LO12_NC     =>"RelocationType::R_AARCH64_LDST8_ABS_LO12_NC",
            RelocationType::R_AARCH64_TSTBR14               =>"RelocationType::R_AARCH64_TSTBR14",
            RelocationType::R_AARCH64_CONDBR19              =>"RelocationType::R_AARCH64_CONDBR19",
            RelocationType::R_AARCH64_JUMP26                =>"RelocationType::R_AARCH64_JUMP26",
            RelocationType::R_AARCH64_CALL26                =>"RelocationType::R_AARCH64_CALL26",
            RelocationType::R_AARCH64_LDST16_ABS_LO12_NC    =>"RelocationType::R_AARCH64_LDST16_ABS_LO12_NC",
            RelocationType::R_AARCH64_LDST32_ABS_LO12_NC    =>"RelocationType::R_AARCH64_LDST32_ABS_LO12_NC",
            RelocationType::R_AARCH64_LDST64_ABS_LO12_NC    =>"RelocationType::R_AARCH64_LDST64_ABS_LO12_NC",
            RelocationType::R_AARCH64_LDST128_ABS_LO12_NC   =>"RelocationType::R_AARCH64_LDST128_ABS_LO12_NC",
            RelocationType::R_AARCH64_MOVW_PREL_G0          =>"RelocationType::R_AARCH64_MOVW_PREL_G0",
            RelocationType::R_AARCH64_MOVW_PREL_G0_NC       =>"RelocationType::R_AARCH64_MOVW_PREL_G0_NC",
            RelocationType::R_AARCH64_MOVW_PREL_G1          =>"RelocationType::R_AARCH64_MOVW_PREL_G1",
            RelocationType::R_AARCH64_MOVW_PREL_G1_NC       =>"RelocationType::R_AARCH64_MOVW_PREL_G1_NC",
            RelocationType::R_AARCH64_MOVW_PREL_G2          =>"RelocationType::R_AARCH64_MOVW_PREL_G2",
            RelocationType::R_AARCH64_MOVW_PREL_G2_NC       =>"RelocationType::R_AARCH64_MOVW_PREL_G2_NC",
            RelocationType::R_AARCH64_MOVW_PREL_G3          =>"RelocationType::R_AARCH64_MOVW_PREL_G3",
            RelocationType::R_AARCH64_COPY                  =>"RelocationType::R_AARCH64_COPY",
            RelocationType::R_AARCH64_GLOB_DAT              =>"RelocationType::R_AARCH64_GLOB_DAT",
            RelocationType::R_AARCH64_JUMP_SLOT             =>"RelocationType::R_AARCH64_JUMP_SLOT",
            RelocationType::R_AARCH64_RELATIVE              =>"RelocationType::R_AARCH64_RELATIVE",
            RelocationType::R_AARCH64_TLS_DTPREL64          =>"RelocationType::R_AARCH64_TLS_DTPREL64",
            RelocationType::R_AARCH64_TLS_DTPMOD64          =>"RelocationType::R_AARCH64_TLS_DTPMOD64",
            RelocationType::R_AARCH64_TLS_TPREL64           =>"RelocationType::R_AARCH64_TLS_TPREL64",
            RelocationType::R_AARCH64_TLSDESC               =>"RelocationType::R_AARCH64_TLSDESC",
            RelocationType::R_AARCH64_IRELATIVE             =>"RelocationType::R_AARCH64_IRELATIVE",
        };
        write!(f, "{}", str)
    }
}
